﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace Controllers
{
    public class UsuarioController
    {
        public static Usuario ObtenerObjeto(OleDbDataReader reader)
        {
            var usuario = new Usuario();

            if (reader["Usuario_UserName"] != DBNull.Value)
                usuario.Usuario_UserName = (string)reader["Usuario_UserName"];
            if (reader["Usuario_Password"] != DBNull.Value)
                usuario.Usuario_Password = (string)reader["Usuario_Password"];
            if (reader["Usuario_Habilitado"] != DBNull.Value)
                usuario.Usuario_Habilitado = (bool)reader["Usuario_Habilitado"];
            if (reader["Usuario_Id"] != DBNull.Value)
                usuario.Usuario_Id = (int)reader["Usuario_Id"];
            if (reader["Usuario_Intentos"] != DBNull.Value)
                usuario.Usuario_Intentos = (int)reader["Usuario_Intentos"];

            return usuario;
        }

        public static List<Usuario> ObtenerTodos(string where, int pagina, int cantidadRegistros)
        {
            var list = new List<Usuario>();

            var sql = "Select TOP " + cantidadRegistros + " * From Superacidos.Usuario";

            if (pagina > 1)
            {
                int limiteAnterior = (pagina - 1) * cantidadRegistros;


                var filtrospaginador = !string.IsNullOrEmpty(where)
                                       ? " Usuario_Id NOT IN " + "(Select TOP " + limiteAnterior +
                                         " Usuario_Id from Superacidos.Usuario WHERE " + where +
                                         " ORDER BY Usuario_Id) "
                                       : " Usuario_Id NOT IN " + "(Select TOP " + limiteAnterior +
                                         " Usuario_Id from Superacidos.Usuario ORDER BY Usuario_Id) ";


                if (!string.IsNullOrEmpty(where))
                {
                    where += " AND ";
                }
                where += filtrospaginador;
            }


            if (!string.IsNullOrEmpty(where))
            {
                sql += " WHERE " + where;
            }

            var reader = ConexionBaseDeDatos.GetData(sql, CommandType.Text);

            if (reader.HasRows)
            {
                while (reader.Read())
                {
                    list.Add(ObtenerObjeto(reader));
                }
            }

            return list;
        }

        public static int ObtenerCantidad(string where)
        {
            var sql = "Select count(*) as Cantidad From Superacidos.Usuario";

            if (!string.IsNullOrEmpty(where))
            {
                sql += " WHERE " + where;
            }
            var cantidad = 0;
            var reader = ConexionBaseDeDatos.GetData(sql, CommandType.Text);

            if (reader.HasRows)
            {
                reader.Read();
                if (reader["Cantidad"] != DBNull.Value)
                    cantidad = (int)reader["Cantidad"];

            }

            return cantidad;
        }

        public static List<string> ObtenerFuncionalidadesPorUsuario(int usuarioId)
        {
            var sql = "SELECT f.Funcionalidad_Nombre" +
                      " FROM SUPERACIDOS.Usuario_Rol ur" +
                      " INNER JOIN SUPERACIDOS.Rol r ON  r.Rol_id = ur.UsRo_RolId" +
                      " INNER JOIN SUPERACIDOS.Rol_Funcionalidad rf ON rf.RoFu_RolId = ur.UsRo_RolId " +
                      " INNER JOIN SUPERACIDOS.Funcionalidad f ON f.Funcionalidad_Id = rf.RoFu_FuncionalidadId" +
                      " WHERE ur.UsRo_UsuarioId = " + usuarioId;

            var reader = ConexionBaseDeDatos.GetData(sql, CommandType.Text);

            var list = new List<string>();
            if (reader.HasRows)
            {
                while (reader.Read())
                {
                    list.Add((string)reader["Funcionalidad_Nombre"]);
                }
            }

            return list;
        }

        public static void Eliminar(int usuarioId)
        {
            var sql = "update SUPERACIDOS.Usuario set usuario_habilitado = 0 where usuario_Id = " + usuarioId;
            ConexionBaseDeDatos.Guardar(sql, CommandType.Text);
        }

        public static string Hash(string value)
        {
            var encoder = new UTF8Encoding();
            var sha256hasher = new SHA256Managed();
            byte[] hashedDataBytes = sha256hasher.ComputeHash(encoder.GetBytes(value));
            return byteArrayToString(hashedDataBytes);

        }

        private static string byteArrayToString(byte[] inputArray)
        {
            var output = new StringBuilder("");
            for (int i = 0; i < inputArray.Length; i++)
            {
                output.Append(inputArray[i].ToString("X2"));
            }
            return output.ToString();
        }

        public static void Agregar(Usuario usuario, List<Rol> listaRoles)
        {
            var conn = ConexionBaseDeDatos.GetConnection();
            var trans = conn.BeginTransaction();

            try
            {
                //guardo usuario
                var sql = "insert into SUPERACIDOS.usuario (Usuario_UserName,Usuario_Password,Usuario_Habilitado,Usuario_Intentos) values" +
                          "('{0}','{1}',{2},0)";

                sql = string.Format(sql, usuario.Usuario_UserName, usuario.Usuario_Password,
                    usuario.Usuario_Habilitado ? "1" : "0");
                ConexionBaseDeDatos.Guardar(sql, CommandType.Text, trans);

                //obtengo el id del usuario que acabo de agregar
                usuario.Usuario_Id = ConexionBaseDeDatos.ObtenerUltimoAgregado(trans);

                //guardo roles
                GuardarRoles(listaRoles, usuario, trans);


                trans.Commit();
            }
            catch (Exception)
            {
                trans.Rollback();
            }
        }

        public static void Modificar(Usuario usuario, List<Rol> listaRoles)
        {

            var conn = ConexionBaseDeDatos.GetConnection();
            var trans = conn.BeginTransaction();

            try
            {
                //modifico usuario
                var sql = "update superacidos.usuario set usuario_username = '{0}', usuario_password = '{1}', usuario_habilitado = {2} where usuario_id = {3}";
                sql = string.Format(sql, usuario.Usuario_UserName, usuario.Usuario_Password, usuario.Usuario_Habilitado ? "1" : "0", usuario.Usuario_Id);
                ConexionBaseDeDatos.Guardar(sql, CommandType.Text, trans);

                //boro todos los roles asignados
                sql = "delete from superacidos.Usuario_Rol where UsRo_UsuarioId =" + usuario.Usuario_Id;
                ConexionBaseDeDatos.Guardar(sql, CommandType.Text, trans);

                //asigno los que corresponda
                GuardarRoles(listaRoles, usuario, trans);

                trans.Commit();
            }
            catch (Exception)
            {
                trans.Rollback();
            }
        }

        private static void GuardarRoles(List<Rol> listaRoles, Usuario usuario, OleDbTransaction trans)
        {
            var sql = "";
            foreach (var rol in listaRoles)
            {
                if (rol.Rol_Seleccionado)
                {
                    sql = string.Format("insert into SUPERACIDOS.Usuario_Rol (UsRo_UsuarioId,UsRo_RolId) Values ({0},{1})", usuario.Usuario_Id, rol.Rol_Id);
                    ConexionBaseDeDatos.Guardar(sql, CommandType.Text, trans);
                }
            }
        }

        public static List<Rol> ObtenerRolesHabilitados(int usuarioID)
        {
            var sql = "SELECT * ,SUPERACIDOS.permisoHabilitado (r.Rol_id," + usuarioID + ") PermisoHabilitado FROM SUPERACIDOS.rol r " + 
                      " WHERE r.Rol_Habilitado = 1";

            var listRoles = new List<Rol>();
            var reader = ConexionBaseDeDatos.GetData(sql, CommandType.Text);

            if (reader.HasRows)
            {
                while (reader.Read())
                {
                    var rol = new Rol();

                    if (reader["Rol_Id"] != DBNull.Value)
                        rol.Rol_Id = (int)reader["Rol_Id"];
                    if (reader["Rol_Nombre"] != DBNull.Value)
                        rol.Rol_Nombre = (string)reader["Rol_Nombre"];
                    if (reader["PermisoHabilitado"] != DBNull.Value)
                        rol.Rol_Seleccionado = (bool)reader["PermisoHabilitado"];

                    listRoles.Add(rol);
                }
            }

            return listRoles;
        }
    }
}
